/*
 * @title interfaceMenu.c
 * @brief Fonctions qui gèrent l'affichage du menu et le traitement du mot instruction en cours.
 * @author Nathalie Kauv & Laura Martellotto
 *
 * @date 27 déc. 2011
 */
#include <stdlib.h>
#include <stdio.h>
#include "interfaceMenu.h"



/**
 * @brief Chargement du programme
 * @param prog Tableau de "mot" représentant le programme à exécuter
 * Ré-initialise les registres et la mémoire à zéro,
 *          puis re-charge le programme en cours dans la mémoire.
 */
void chargerProgramme(mot prog[])
{
    reg.pc = 0;
    reg.sp = TAILLE_MEM - 1;
    int i;
    for ( i = 0; i < TAILLE_MEM; ++i)
    {
        memoire[i].brut = 0;
    }

    for ( i = 0; i < 8; ++i)
    {
        reg.registres[i] = 0;
    }

    for ( i = 0; prog[i].brut != NULL; ++i)
    {
        memoire[i] = prog[i];
    }
}

/**
 * @brief Fonction de traitement d'un mot instruction.
 * @param codInst Mot instruction que l'on souhaite traiter.
 *
 * En fonction du code opération de l'objet codInst,
 *          cette fonction va faire appel à la fonction adéquate de traitement
 */
int traiterMot(mot codInst)
{
    int returnHalt = 0;
    switch(codInst.codage.codeop) {
    case LOAD :
        traiterLoad(codInst);
        reg.pc ++;
        break;
    case STORE :
        traiterStore(codInst);
        reg.pc ++;
        break;
    case ADD :
        traiterAdd(codInst);
        reg.pc ++;
        break;
    case SUB :
        traiterSub(codInst);
        reg.pc ++;
        break;
    case JMP :
        traiterJmp(codInst);
        break;
    case JEQ :
        traiterJeq(codInst);
        break;
    case CALL :
        traiterCall(codInst);
        break;
    case HALT :
        halt();
        returnHalt = 1;
        reg.pc++;
        break;
    case RET :
        ret();
        break;
    case PUSH :
        traiterPush(codInst);
        reg.pc++;
        break;
    case POP :
        traiterPop(codInst);
        reg.pc++;
        break;
    default :
        printf("Erreur, instruction non reconnue à l'adresse %d\n\n", reg.pc);
        reg.pc ++;
    }
    return returnHalt;
}


/**
 * @brief Lancer le menu permettant d'exécuter le programme.
 * @param prog Tableau de "mot" représentant le programme à exécuter
 * Lance le menu du projet qui propose à l'utilisateur plusieurs options :
 *      [0] Quitter l'émulateur.
 *      [1] Afficher les registres.
 *      [2] Afficher la mémoire.
 *      [3] Exécuter le programme en entier.
 *      [4] Exécuter le programme pas à pas.
 */
void lancerProgramme(mot prog[])
{
    int rep_menu = 30;
    int finPasAPas = 0;
    char * pasAPas = '\n';

    chargerProgramme(prog);

    printf(  "\n\t\t==================================\
            \n\t              PROJET EMULATEUR PROCSI\
            \n\t                KAUV - MARTELLOTTO \
            \n\t\t==================================\
            \n\
    \n\t Programme chargé en mémoire.");
    while (rep_menu != 0) {
        printf("\nMenu : \
                \n\t[0] Quitter l'émulateur. \
                \n\t[1] Afficher les registres. \
                \n\t[2] Afficher la mémoire. \
                \n\t[3] Exécuter le programme en entier. \
                \n\t[4] Exécuter le programme pas à pas. \
        \n\n\t\tChoix : ");
        scanf("%d", &rep_menu);

        fflush(stdin);
        printf("\n");

        switch(rep_menu) {
        case 1 :
            afficherRegistres();
            break;
        case 2 :
            afficherMemoire();
            break;
        case 3 :
            chargerProgramme(prog);
            int isHalt = 0;
            for ( ; memoire[reg.pc].brut != NULL && isHalt != 1; )
            {
                if (memoire[reg.pc].codage.codeop == HALT)
                    isHalt = 1;
                isHalt = traiterMot(memoire[reg.pc]);
            }
            break;
        case 4 :
            if (finPasAPas == 1)
            {
                chargerProgramme(prog);
                printf("Programme chargé en mémoire.\n");
                finPasAPas = 0;
            }
            printf("Taper [enter] pour poursuivre l'exécution pas à pas.\n");
            printf("Entrer une touche pour stopper l'exécution pas à pas.\n");
            printf("L'exécution pourra alors être reprise ensuite.\n");
            pasAPas = '\n';
            while ((pasAPas = getchar()) == '\n' && finPasAPas == 0)
            {
                if (memoire[reg.pc].brut == NULL) {
                    finPasAPas = 1;
                    printf("Fin du programme.");
                }
                else {
                    system("clear");
                    traiterMot(memoire[reg.pc]);
                    afficherRegistres();
                    afficherMemoire();
                }
            }
            break;
        case 0:
            rep_menu = 0;
            return;
        }
    }

}



